#ifndef _MY_PTRS_H_
#define _MY_PTRS_H_


template<class T> class my_ptr
{
public:
   my_ptr() : px(NULL), pn(0)
   {;}

   my_ptr(T* p) : px(p), pn(0)
   {;}

   // XXX: This is probably very bad
   template<class Y>
   my_ptr(my_ptr<Y> const& r) : px(r.px), pn(r.pn)
   {;}

   my_ptr<T>& operator=(my_ptr<T> const& r)
   {
      px = r.px;
      pn = r.pn;
      return *this;
   }

   bool operator==(my_ptr<T> const& r)
   {
      return get() == r.get();
   }

   void incCount()
   { pn+=1; }
   void decCount()
   {
      if(pn > 0)
      {
         pn -= 1;
         if(0 == pn)
         { delete px; }
      }
   }

   T& operator*() const
   { return *px; }

   T* operator->() const
   { return px; }

   unsigned count() const
   { return pn; }

   T* get() const
   { return px; }

   T* px;
   unsigned pn;
};

template<class T> class ref_ptr
{
public:
   ref_ptr(my_ptr<T> const& r)
   {
      ptr = const_cast<my_ptr<T>*>(&r);
      (*ptr).incCount();
   }

   ref_ptr(ref_ptr<T> const& r)
   {
      ptr = r.ptr;
      (*ptr).incCount();
   }

   template<class U>
   operator my_ptr<U>() const
   {
      return *ptr;
   }

   ~ref_ptr()
   {
      (*ptr).decCount();
   }

   T& operator*() const
   { return *(get()); }

   T* operator->() const
   { return get(); }

   unsigned count() const
   { return (*ptr).pn; }

   T* get() const
   { return (*ptr).get(); }


   my_ptr<T>* ptr;
};

template<class T>
ref_ptr<T> ToRefPtr(my_ptr<T>& ptr)
{
   return ref_ptr<T>(ptr);
}

template<class T>
my_ptr<T> ToMyPtr(ref_ptr<T>& ptr)
{
   return *(ptr.ptr);
}


#endif
